import java.util.concurrent.Semaphore;
 
//Solving the mutual exclusion problem using Semaphore class
 
class Process2 extends Thread
{
 
    private int id;
 
    private Semaphore sem;
 
    public Process2(int i, Semaphore s)
    {
        id = i;
        sem = s;
    }
 
    private int random(int n)
    {
        return (int) Math.round(n * Math.random() - 0.5);
    }
 
    private void busy()
    {
        try
        {
            sleep(random(500));
        } catch (InterruptedException e)
        {
        }
    }
 
    private void noncritical()
    {
        System.out.println("Thread " + id + " is NON critical");
        busy();
    }
 
    private void critical()
    {
        System.out.println("Thread " + id + " entering critical section");
        busy();
        System.out.println("Thread " + id + " leaving critical section");
    }
 
    public void run()
    {
        for (int i = 0; i < 2; ++i)
        {
            noncritical();
            try
            {
                sem.acquire();
            } catch (InterruptedException e)
            {
                // ...
            }
            critical();
            sem.release();
        } 
    }
 
    public static void main(String[] args)
    {
        final int N = 4;
 
        System.out.println("Busy waiting...");
 
        //Semaphore(int permits, boolean fair) 
        Semaphore sem = new Semaphore(N, true);
 
        Process2 p[] = new Process2[N];
 
        for (int i = 0; i < N; i++)
        {
            p[i] = new Process2(i, sem);
            p[i].start();
        }
    }
}
